﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CastleDefender.Platform;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using CastleDefender.ConfigFolder;

namespace CastleDefender.Object
{
    public partial class Arrow  : Animation2D
    {

        #region VARIABLE

        protected Rectangle recArrowhead;
        protected Rectangle recArrowmid;
        protected bool blnShoot;
        protected TimeSpan tsTimeSpanMotion;
        protected float fltTime;
        protected float fltDeltaTimeArrowmid;
        protected int intPower;
        protected float fltAngleOfAttack;
        protected bool blnOnTarget;

        private int XInitArrowhead, YInitArrowhead;
        private int XInitArrowmid, YInitArrowmid;

        #endregion

        #region CONSTRUCTOR

        public Arrow(Game myGame, ref Texture2D texture, int widthFrame, int heightFrame,
           Vector2 position, float rotation)
            : base(myGame, ref texture, widthFrame, heightFrame,false,false, position, Config.ArrowTimeAnimation)
        {

            fltRotation = rotation;
            fltTime = 0;
            fltDeltaTimeArrowmid = 0;
            fltAngleOfAttack = 0;
            intPower = 0;
            blnShoot = false;
            tsTimeSpanMotion = TimeSpan.Zero;

            //Góc xoay
            vecOrigin = new Vector2(intWidthFrame / 2, intHeightFrame / 2);

            //Khung bao ngoài của mũi tên
            Bounds = new Rectangle((int)Position.X - intWidthFrame / 2, (int)Position.Y - intWidthFrame / 2, intWidthFrame, intHeightFrame);

            //Khung bao của đầu mũi tên
            recArrowhead = new Rectangle((int)Position.X - Config.ArrowWidthSpearHead / 2, (int)Position.Y - Config.ArrowHeightSpearHead / 2,
                Config.ArrowWidthSpearHead, Config.ArrowHeightSpearHead);

            //Khung bao của đuôi mũi tên
            recArrowmid = new Rectangle((int)Position.X - Config.ArrowWidthSpearHead / 2, (int)Position.Y - Config.ArrowHeightSpearHead / 2,
                Config.ArrowWidthSpearHead, Config.ArrowHeightSpearHead);

            //Tọa độ đầu của đầu mũi tên (sử dụng cho tính toan chuyển trục tọa độ)
            XInitArrowhead = recArrowhead.X;
            YInitArrowhead = recArrowhead.Y;

            //Tọa độ đầu của đuôi mũi tên (sử dụng cho tính toan chuyển trục tọa độ)
            XInitArrowmid = recArrowmid.X;
            YInitArrowmid = recArrowmid.Y;
        }

        #endregion

        #region PUBLIC METHOD

        public override void Update(GameTime gameTime)
        { 
            if (Visible)
            {
                //Bắn mũi tên
                if (blnOnTarget && ActiveFrame == frames[State].Count - 1)
                {
                    Enabled = false;
                }
     
                if (blnShoot && !blnOnTarget)
                {
                    ShootArrow(gameTime);
                }
            }

            base.Update(gameTime);
        }

        #endregion

        #region PRIVATE METHOD

        //Bắn mũi tên
        private void ShootArrow(GameTime gameTime)
        {
            //Thiết lập bao ngoài của mũi tên
            recBounds = new Rectangle((int)vecPosition.X - intWidthFrame / 2, (int)vecPosition.Y - intWidthFrame / 2, intWidthFrame / 2, intHeightFrame);

            //Chuyển thời gian game time thành thời gian thực của mũi tên theo mili giây
            tsTimeSpanMotion += gameTime.ElapsedGameTime;
            if (tsTimeSpanMotion > TimeSpan.FromMilliseconds(Config.ArrowTimeSpanMotion))
            {
                tsTimeSpanMotion -= TimeSpan.FromMilliseconds(Config.ArrowTimeSpanMotion);
                fltTime += Config.ArrowTimeInOrbit;
            }

            //Thực hiện bắn mũi tên
            Motion(ref recArrowhead, XInitArrowhead, YInitArrowhead, fltTime);

            //Tính toán khoảng thời gian tạo khoảng cách giữa đầu mũi tên và điểm giữa mũi tên
            if (new Vector2(recArrowhead.X - recArrowmid.X, recArrowhead.Y - recArrowmid.Y).Length() > (intHeightFrame - Config.ArrowHeightSpearHead) / 2 && fltDeltaTimeArrowmid == 0)
            {
                fltDeltaTimeArrowmid = fltTime;
            }

            //Điểm giữa mũi tên bay khi cách đầu mũi tên một khoảng thời gian nhất định
            if (fltDeltaTimeArrowmid != 0)
            {
                Motion(ref recArrowmid, XInitArrowmid, YInitArrowmid, fltTime - fltDeltaTimeArrowmid);
            }

            //Thay đổi tọa độ mũi tên theo 2 hình chữ nhật ảo tính trước
            Vector2 PosArrowhead = new Vector2(recArrowhead.Center.X, recArrowhead.Center.Y);
            Vector2 PosArrowmid = new Vector2(recArrowmid.Center.X, recArrowmid.Center.Y);

            //Position = PositionArrow(PosArrowhead - PosArrowmid, PosArrowhead, (HeightFrame - Config.ArrowHeighSpeartHead) / 2);
            vecPosition = PosArrowmid;
            fltRotation = AngleRotation(PosArrowhead - PosArrowmid);
        }

        //Tính tọa độ một hình hộp bị ném với vận tốc đầu Vo = Power
        private void Motion(ref Rectangle rect, int XInit, int YInit, float time)
        {
            int X11 = 0, Y11 = 0;
            float A = Config.PI / 2 - fltAngleOfAttack;

            //Tính tọa độ hình hộp đã được chuyển trục tọa độ khi ném xiên 1 góc A
            X11 = (int)(intPower * Math.Cos(A) * time);
            Y11 = (int)(intPower * Math.Sin(A) * time - Config.VectorG.Length() * time * time / 2);

            rect.X = X11 + XInit;
            rect.Y = -Y11 + YInit;
        }

        #endregion

        #region PUBLIC PROPERTIES

        //Nhận, trả giá trị cho góc quay rotation
        public float Rotation
        {
            get { return fltRotation; }
            set
            {
                if (!blnShoot)
                {
                    fltRotation = value;
                }
            }
        }

        //Nhận, trả giá trị cho Power năng lượng ban đầu truyền vào
        public int Power
        {
            get { return intPower; }
            set 
            {
                //Chỉ được phép truyền năng lượng 1 lần duy nhất
                if (intPower == 0)
                {
                    intPower = value;
                }
            }
        }

        //Nhận giá trị cờ hiệu tấn công và thiết lập góc bắn của tên
        public bool Shoot
        {
            get { return blnShoot; }
            set
            {
                //Không thể thay đổi trạng thái cờ hiệu khi cờ hiệu đã đúng
                if (blnShoot == false && value == true)
                {
                    fltAngleOfAttack = fltRotation;
                    blnShoot = value;
                }
            }
        }

        //Khung bao của đầu mũi tên
        public Rectangle ArrowHeadBounds
        {
            get { return recArrowhead; }
        }

        //Nhận trả giá trị blnOnTarget
        public bool OnTarget
        {
            get { return blnOnTarget; }
            set 
            {
                if (value && !blnOnTarget)
                {
                    State = 1;
                    ActiveFrame = 0;
                }
                blnOnTarget = value;
            }
        }
        #endregion

    }
}
